﻿using Chemistry.Models;
using Chemistry.WorkFlow;
using GalaSoft.MvvmLight.Command;
using OPCAutomation;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO.Ports;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Navigation;
using Chemistry.Tools;
using GLCommon;

namespace Chemistry.ViewModels
{
    public class EquipmentViewModel:VmBase
    {
        #region 字段 
       
        private CurrentExamingWindow _currentExamingWindow;
        private Examinee _currentExaminee;
        private WorkFlowBase _currentFlow;
        private ConfigModel _config ;
        private List<ExaminationPoint> _points;
        private SerialPort _port;
        private OPCServer _opcServer;
        private ExamInfo _selectedExamInfo;
        private List<ButtonInformation> _buttonInformations;

        private bool _canInput;
        private bool _canLink;
        private bool _canBegin;
        private bool _canCheckstate;
        private bool _canDirectInto;
        private GuideConfigModel _guideConfigModel;
        #endregion

        #region 通知 属性

        private ObservableCollection<ExamInfo> _examinfoes;
        public ObservableCollection<ExamInfo> ExamInfoes
        {
            get { return _examinfoes; }
            set { _examinfoes = value; RaisePropertyChanged("ExamInfoes"); }
        }
        
        public ExamInfo SelectedExamInfo
        {
            get { return _selectedExamInfo; }
            set { _selectedExamInfo = value; RaisePropertyChanged("SelectedExamInfo"); }
        }

        private bool _isopcconnected;

        public bool IsOPCConnected
        {
            get { return _isopcconnected; }
            set { _isopcconnected = value; RaisePropertyChanged("IsOPCConnected"); }
        }

        private bool _isserialportconnected;

        public bool IsSerialPortConnected
        {
            get { return _isserialportconnected; }
            set { _isserialportconnected = value; RaisePropertyChanged("IsSerialPortConnected"); }
        }


        private bool _isinner;

        public bool IsInner
        {
            get { return _isinner; }
            set { _isinner = value; RaisePropertyChanged("IsInner"); }
        }

        #endregion

        #region 命令
        public RelayCommand LinkCommand { get; set; }
        public RelayCommand CheckStateCommand { get; set; }
        public RelayCommand InputCommand { get; set; }
        public RelayCommand SelectQuestionCommand { get; set; }
        public RelayCommand BeginCommand { get; set; }
        public RelayCommand CheckSelectedCommand { get; set; }
        public RelayCommand DirectIntoExamingCommand { get; set; }  
        #endregion

        public EquipmentViewModel()
        {
            InitMessage();
            LinkCommand = new RelayCommand(LinkExec, () => _canLink);
            InputCommand = new RelayCommand(InputExec, () => _canInput);
            BeginCommand = new RelayCommand(BeginExec, () => _canBegin);
            CheckStateCommand = new RelayCommand(CheckStateExec, () => _canCheckstate);
            DirectIntoExamingCommand = new RelayCommand(DirectIntoExamingExec, () => _canDirectInto);
        }

       

        private void InitMessage()
        {
            //不用
            Register(this, MessageToken.ShowExamWindow, (i) =>
            {
                _config = Tool.GetConfig();
                IsInner = _config.IsInner;
                InitExamInfoes();

                _canLink = true;
                _canInput = false;
                _canCheckstate = false;
                _canBegin = false;
                _canDirectInto = false;
            });
            //改用这个
            Register<ExamInfo>(this, MessageToken.ShowGuideWindow, (i) =>
            {
                ExamInfoes = new ObservableCollection<ExamInfo>();
                //SelectedExamInfo = new ExamInfo()
                //{
                //    Index = 1,
                //    ExamState = ExamState.未连接,

                //};

               
                //InitExamInfoes();
                SelectedExamInfo = i;
                _canInput = false;
                _currentExaminee = i.Examinee;
                SelectedExamInfo.Name = i.ExamineeRemote.name;
                SelectedExamInfo.ExamState = ExamState.未连接;
                SelectedExamInfo.Index = 1;
                SelectedExamInfo.LoginDate = DateTime.Now;
                SelectedExamInfo.TicketId = i.ExamineeRemote.nr;
                ExamInfoes.Add(SelectedExamInfo);
            });
            //改用这个
            Register<bool>(this, MessageToken.ShowEquipmentWindow, (i) =>
            {
                _config = Tool.GetConfig();
                IsInner = i;
                _guideConfigModel = Tool.GetGuideConfigModel();

                _canLink = true;
                _canInput = false;
                _canCheckstate = false;
                _canBegin = false;
                _canDirectInto = false;

                
            });
            

            //确认完毕准考证之后 开始考试
            Register<ExamInfo>(this, MessageToken.BeginExaming, async (i) =>
            {
                _selectedExamInfo = i;
                _canInput = false;
                _currentExaminee = i.Examinee;
                var ispass = await BeginExaming();
                if (ispass)
                {
                    ExamInfoMessage msg = new ExamInfoMessage()
                    {
                        ExamInfo = _selectedExamInfo,
                        IsFirstShow = true,
                        ButtonInformations = _buttonInformations,
                        Points = _points,
                         WorkFlow = _currentFlow
                    };
                    _canBegin = false;
                    _canCheckstate = true;
                    _currentExamingWindow = CurrentExamingWindow.NormalExaming;
                    //开始考试，弹出考试状态窗口
                    Send<ExamInfoMessage>(msg, MessageToken.ShowExamingWindow);
                }
            });

            Register<List<ExaminationPoint>>(this, MessageToken.ShowInputNumber, (i) =>
            {
                _points = i;
                _selectedExamInfo.Permission.CanCheckSelected = true;
            });

            Register<object>(this,MessageToken.StopExaming,
                (i) =>
                    {
                        _currentFlow.Close();
                    });
            Register<bool>(this, MessageToken.IsExaming, (i) =>
            {
                _canInput = !i;
               // _canBegin = !i;
                _canDirectInto = !i;
            });
        }

      

        #region 命令方法

       /// <summary>
       /// 直接进入考试
       /// </summary>
       private async void DirectIntoExamingExec()
        {
            if (_port != null && !_port.IsOpen)
            {
                _port.Open();
            }
           Send<string>("加载题目中......", MessageToken.ShowExamLoadMessage);
           bool ispass = false;
           await Task.Delay(500);
           _currentFlow = GetFlow();

           string msg = await _currentFlow.CheckDefault();
           if (string.IsNullOrEmpty(msg))
           {
               _currentFlow.Begin();
               ispass = true;
               _selectedExamInfo.ExamState = ExamState.考试中;
               Send<string>("加载题目中......", MessageToken.CloseExamLoadMessage);
           }
           else
           {
               _selectedExamInfo.ExamState = ExamState.空闲;
               Send<string>("加载题目中......", MessageToken.CloseExamLoadMessage);
               await Task.Delay(500);
               Send<string>(msg, MessageToken.ShowExamMessage);
           }
           if (ispass)
           {
               ExamInfoMessage exmsg = new ExamInfoMessage()
               {
                   ExamInfo = _selectedExamInfo,
                   IsFirstShow = true,
                   ButtonInformations = _buttonInformations,
                   Points = _points,
                   WorkFlow =  _currentFlow
               };
               _canInput = false;
               _canCheckstate = true;
               _canDirectInto = false;
               //开始考试，弹出考试状态窗口
               _currentExamingWindow = CurrentExamingWindow.DirectExaming;
               Send<ExamInfoMessage>(exmsg, MessageToken.ShowDirectExamingWindow);
           }
       }

       /// <summary>
       /// 连接设备
       /// </summary>
       private void LinkExec()
       {
           if (_config != null)
           {
               if (_selectedExamInfo != null)
               {
                   bool isOpcLinked = LinkOpcServer(_config);
                   if (IsInner)
                   {
                       if (isOpcLinked)
                       {
                           InitFlowButtonInfo(_guideConfigModel.ClassName);
                           _canBegin = true;
                           _canLink = false;
                           _canInput = true;
                           _canDirectInto = true;
                           SelectedExamInfo.ExamState = ExamState.空闲;
                       }
                   }
                   else
                   {
                       if (_buttonInformations != null)
                           _buttonInformations.Clear();
                       this.IsSerialPortConnected = LinkSerialPort(_config);
                       if (IsOPCConnected && IsSerialPortConnected)
                       {
                           _canBegin = true;
                           _canLink = false;
                           _canInput = true;
                           _canDirectInto = true;
                           SelectedExamInfo.ExamState = ExamState.空闲;
                       }
                   }
               }

               
           }
       }

        /// <summary>
        /// 开始考试
        /// </summary>
        private async void BeginExec()
       {
           if (_port != null && !_port.IsOpen)
           {
               _port.Open();
           }
            var ispass = await BeginExaming();
            if (ispass)
            {
                ExamInfoMessage msg = new ExamInfoMessage()
                {
                    ExamInfo = _selectedExamInfo,
                    IsFirstShow = true,
                    ButtonInformations = _buttonInformations,
                    Points = _points,
                    WorkFlow = _currentFlow
                };
                _canBegin = false;
                _canCheckstate = true;
                _currentExamingWindow = CurrentExamingWindow.NormalExaming;
                //开始考试，弹出考试状态窗口
                Send<ExamInfoMessage>(msg, MessageToken.ShowExamingWindow);
            }





            //Send<string>("加载题目中......", MessageToken.ShowExamLoadMessage);
            //bool ispass = false;
            //await Task.Delay(500);
            //_currentFlow = GetFlow();

            //string msg = await _currentFlow.CheckDefault();
            //if (string.IsNullOrEmpty(msg))
            //{
            //    _currentFlow.Begin();
            //    ispass = true;
            //    _selectedExamInfo.ExamState = ExamState.考试中;
            //    _selectedExamInfo.Permission.CanCommit = true;
            //    _selectedExamInfo.Permission.CanCheckState = true;
            //    _selectedExamInfo.Permission.CanPrint = false;
            //    _selectedExamInfo.Permission.CanInput = false;
            //    _selectedExamInfo.Permission.CanBeginExam = false;
            //    _selectedExamInfo.Permission.CanSelectQuestion = false;
            //    Send<string>("加载题目中......", MessageToken.CloseExamLoadMessage);
            //}
            //else
            //{
            //    Send<string>("加载题目中......", MessageToken.CloseExamLoadMessage);
            //    await Task.Delay(500);
            //    Send<string>(msg, MessageToken.ShowExamMessage);
            //    _selectedExamInfo.Permission.CanBeginExam = true;
            //}
            //if (ispass)
            //{
            //    ExamInfoMessage exmsg = new ExamInfoMessage()
            //                              {
            //                                  ExamInfo = _selectedExamInfo,
            //                                  IsFirstShow = true,
            //                                  ButtonInformations = _buttonInformations,
            //                                  Points = _points,
            //                                  WorkFlow = _currentFlow
            //                              };
            //    //开始考试，弹出考试状态窗口
            //    _currentExamingWindow = CurrentExamingWindow.NormalExaming;
            //    Send<ExamInfoMessage>(exmsg, MessageToken.ShowExamingWindow);
            //}
        }

        /// <summary>
        /// 查看考试状态
        /// </summary>
        private void CheckStateExec()
        {
            var msg = new ExamInfoMessage()
                          {
                              ExamInfo = _selectedExamInfo,
                              IsFirstShow = false,
                              ButtonInformations = _buttonInformations,
                              Points = _points,
                              WorkFlow = _currentFlow
                          };
            switch (_currentExamingWindow)
            {
                case CurrentExamingWindow.NormalExaming:
                    Send<ExamInfoMessage>(msg, MessageToken.ShowExamingWindow);
                    break;
                case CurrentExamingWindow.DirectExaming:
                    Send<ExamInfoMessage>(msg, MessageToken.ShowDirectExamingWindow);
                    break;
            }
        }

        private void InitFlowButtonInfo(string className)
        {
            _buttonInformations = new List<ButtonInformation>();
            var config = Tool.GetRegulationButtons(className);
            if (config != null && config.Items.Count > 0)
            {
                foreach (var item in config.Items)
                {
                    ButtonInformation button = new ButtonInformation() { Description = item.Name };
                    _buttonInformations.Add(button);
                }
            }
        }

        private void InputExec()
        {
            Send(MessageToken.ShowInputNumber);
        }

       
        #endregion

        #region 连接设备和组态软件
        private bool LinkSerialPort(ConfigModel configModel)
        {
            var issuccess = false;
            try
            {
                if (_port != null)
                {
                    _port.Close();
                }

                _port = new SerialPort
                {
                    StopBits = configModel.StopBit,
                    DataBits = configModel.DataBit,
                    Parity = configModel.Parity,
                    BaudRate = configModel.BaudRate,
                    PortName = configModel.Name
                };
                try
                {
                    _port.Open();
                    issuccess = true;
                }
                catch (Exception ex)
                {
                    LogTool.WriteErrorLog(ex);
                }
            }
            catch (Exception ex)
            {
                LogTool.WriteErrorLog(ex);
            }

            return issuccess;
        }

        private bool LinkOpcServer(ConfigModel configModel)
        {
            bool issuccess = false;
            try
            {
                Process[] p = Process.GetProcessesByName("McgsRun");

                if (p.Count() == 1)
                {
                    _opcServer = new OPCServer();
                    _opcServer.Connect(configModel.OPCServerName, configModel.IP);
                    _opcServer.ServerShutDown += _opcserver_ServerShutDown;

                    issuccess = true;
                    this.IsOPCConnected = true;
                }
                else if (p.Count() > 1)
                {
                    ShowMessage("请打开任务管理器，结束掉所有\"McgsRun.exe\"进程，然后重新打开组态环境并运行");
                }
                else
                {
                    ShowMessage("请先打开组态软件并运行");
                }
            }
            catch (Exception ex)
            {
                LogTool.WriteErrorLog(ex);
                Console.WriteLine(ex);
                issuccess = false;
                ShowMessage("组态软件连接失败");
            }
            return issuccess;
        }

        void _opcserver_ServerShutDown(string Reason)
        {
            _selectedExamInfo.Permission.CanLink = true;
            this.IsOPCConnected = false;
        }
        #endregion

        #region 私有方法
        void InitExamInfoes()
        {
            ExamInfoes = new ObservableCollection<ExamInfo>();
            SelectedExamInfo = new ExamInfo()
            {
                Index = 1,
                ExamState = ExamState.未连接,
                 
            };

            ExamInfoes.Add(SelectedExamInfo);
        }

        /// <summary>
        /// 确认完之后，开始考试
        /// </summary>
        /// <returns></returns>
        private async Task<bool> BeginExaming()
        {
            if (_port != null && !_port.IsOpen)
            {
                _port.Open();
            }
            Send<string>("加载题目中......", MessageToken.ShowExamLoadMessage2);
            await Task.Delay(500);
            bool ispass = false;
            _selectedExamInfo.TicketId = _currentExaminee.TicketId;
            _selectedExamInfo.LoginDate = DateTime.Now;
            _selectedExamInfo.Examinee = _currentExaminee;
            _selectedExamInfo.Name = _currentExaminee.Name;
            _selectedExamInfo.Score = 0;           

            _currentFlow = GetFlow();

            string msg = await _currentFlow.CheckDefault();
            if (string.IsNullOrEmpty(msg))
            {
                _currentFlow.Begin();
                ispass = true;
                _selectedExamInfo.ExamState = ExamState.考试中;
                Send<string>("加载题目中......", MessageToken.CloseExamLoadMessage2);
            }
            else
            {
                _selectedExamInfo.ExamState = ExamState.考生已登录;
                Send<string>("加载题目中......", MessageToken.CloseExamLoadMessage2);
                await Task.Delay(500);
                Send<string>(msg, MessageToken.ShowExamMessage);
                _canBegin = true;
            }
            return ispass;
        }

        private WorkFlowBase GetFlow()
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            List<object> parameters = new List<object>();
            parameters.Add(_opcServer);
            parameters.Add(_port);
            parameters.Add(IsInner);
            string classfullname = string.Format("Chemistry.WorkFlow.{0}", _guideConfigModel.ClassName);
            object o = assembly.CreateInstance(classfullname, true, BindingFlags.Default, null, parameters.ToArray(), null, null);
            return o as WorkFlowBase;
        } 
        #endregion
    }

    /// <summary>
    /// 当前考试窗口
    /// </summary>
    enum CurrentExamingWindow
    {
        /// <summary>
        /// 正常流程
        /// </summary>
        NormalExaming,
        /// <summary>
        /// 直接进入考试
        /// </summary>
        DirectExaming
    }
}
